﻿#pragma once
#include "yzrutil.h"
#include "array/Array.hpp"
#include "util/Comparator.hpp"
#include "lang/Exception.h"
#include "lang/System.h"
#include "lang/Math.h"
#include "util/Util.h"

namespace yzrilyzr_array{
	EBCLASS(Arrays){
	public:
	template<typename T>
	static void fill(Array<T> &a, u_index fromIndex, u_index toIndex, T val){
		yzrilyzr_util::Util::checkRange(a.length, fromIndex, toIndex);
		for(u_index i=fromIndex; i < toIndex; i++)
			a[i]=val;
	}
	template<typename T>
	static void fill(Array<T> &a, T val){
		fill(a, 0, a.length, val);
	}
	template<typename T>
	static Array<T> copyOf(const Array<T> &original, u_index newLength){
		Array<T> copy(newLength);
		yzrilyzr_lang::System::arraycopy(original, 0, copy, 0,
										 yzrilyzr_lang::Math::min(original.length, newLength));
		return copy;
	}
	template<typename T>
	static Array<T>	copyOfRange(const Array<T> &original, u_index from, u_index to){
		u_index newLength=to - from;
		if(newLength < 0)
			throw yzrilyzr_lang::IllegalArgumentException(
				std::to_string(from) + " > " + std::to_string(to));
		Array<T> copy(newLength);
		yzrilyzr_lang::System::arraycopy(original, from, copy, 0,
										 yzrilyzr_lang::Math::min(original.length - from, newLength));
		return copy;
	}
	static constexpr u_index SOFT_MAX_ARRAY_LENGTH=0x7fffffff - 8; 
	static u_index	newLength(u_index oldLength, u_index minGrowth, u_index prefGrowth){
		u_index prefLength=oldLength + yzrilyzr_lang::Math::max(minGrowth, prefGrowth);
		if(0 < prefLength && prefLength <= SOFT_MAX_ARRAY_LENGTH){
			return prefLength;
		} else{
			return hugeLength(oldLength, minGrowth);
		}
	}
	static u_index hugeLength(u_index oldLength, u_index minGrowth){
		u_index minLength=oldLength + minGrowth;
		if(minLength < 0){
			throw yzrilyzr_lang::OutOfMemoryError(
				yzrilyzr_lang::String("Required array length ") + oldLength + " + " +
				minGrowth + " is too large");
		} else if(minLength <= SOFT_MAX_ARRAY_LENGTH){
			return SOFT_MAX_ARRAY_LENGTH;
		} else{
			return minLength;
		}
	}
	template<typename T>
	static void	sort(Array<T> &a, u_index fromIndex, u_index toIndex, yzrilyzr_util::Comparator<T> c){
		if(c == nullptr){
			std::sort(a._array + fromIndex, a._array + toIndex);
		} else{
			std::sort(a._array + fromIndex, a._array + toIndex, c);
		}
	}
	template<typename T, typename C>
	static std::shared_ptr<Array<T>> cast(std::shared_ptr<Array<C>> src){
		if constexpr(std::is_same_v<T, C>){
			// 类型相同，直接返回原始共享指针
			return std::static_pointer_cast<Array<T>>(src);
		} else{
			// 类型不同，创建新数组
			auto res=std::make_shared<Array<T>>(src->length);
			C * srcA=src->_array;
			T * resA=res->_array;
			for(u_index i=0, l=src->length; i < l; i++){
				resA[i]=static_cast<T>(srcA[i]);
			}
			return res;
		}
	}
	template<typename T, typename C>
	static std::shared_ptr<Array<T>> cast(Array<C> &src){
		if constexpr(std::is_same_v<T, C>){
			// 类型相同，直接返回原始共享指针
			return std::shared_ptr<Array<T>>(&src, [](auto *){});
		} else{
			// 类型不同，创建新数组
			auto res=std::make_shared<Array<T>>(src.length);
			C * srcA=src._array;
			T * resA=res->_array;
			for(u_index i=0, l=src.length; i < l; i++){
				resA[i]=static_cast<T>(srcA[i]);
			}
			return res;
		}
	}
	template<typename... Par>
	static int32_t hashCode(Par... pars){
		int32_t result=0;
		// 使用初始化列表和逗号运算符
		auto list={(result=result * 31 + std::hash<Par>{}(pars), 0)...};
		(void)list; // 避免未使用变量警告
		return result;
	}
	};
}